#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#define NOTFOUND 0
#define FOUND 1

typedef struct{
    char code[6];
    char name[20];
    char description[40];
    int  semesters;
    int  status;
}structCourse;

FILE *fp;

/**------------------------INSERÇÃO-----------------------------**/

int insertCourseFile(structCourse tmpCourse){
    fp = fopen("myCourse", "ab");
    if(!fp){
        printf("O arquivo nao pode ser aberto. Encerrando o programa...\n");
        system("pause");
        exit(0);
    }

    if(fwrite(&tmpCourse, sizeof(structCourse), 1, fp) == 1)
        printf("Curso salvo com sucesso!\n");
    else
        printf("Erro ao salvar o curso!\n");

    system("pause");
    fclose(fp);
}



/**------------------------BUSCA-----------------------------**/

//RETORNA UMA STRUCT COM OS DADOS RESULTANTES DA BUSCA
structCourse* findCourseFile(char keyCode[], char keyName[], char keyPartName[]){
    structCourse tmpCourse;


    fp = fopen("myCourse", "r+b");
    if(!fp){
        printf("O arquivo nao pode ser aberto. Encerrando o programa...\n");
        system("pause");
        exit(0);
    }

    rewind(fp);


    if(!strcmp(keyName, "") && !strcmp(keyPartName, "")){//BUSCA APENAS POR CODIGO
        while (!feof(fp)) {
            fread(&tmpCourse, sizeof(structCourse), 1, fp);
            if(!strcmp(tmpCourse.code, keyCode) && tmpCourse.status == 0){
                fclose(fp);
                return &tmpCourse;
            }
        }
        return NULL;
    }else if(!strcmp(keyCode, "") && !strcmp(keyPartName, "")){ //BUSCA APENAS POR NOME
        while (!feof(fp)) {
            fread(&tmpCourse, sizeof(structCourse), 1, fp);
            if(!strcmp(tmpCourse.name, keyName) && tmpCourse.status == 0){
                fclose(fp);
                return &tmpCourse;
            }
        }
        return NULL;
    }else if(!strcmp(keyCode, "") && !strcmp(keyName, "")){ //BUSCA POR PARTE DO NOME
       while (!feof(fp)) {
           fread(&tmpCourse, sizeof(structCourse), 1, fp);
           if(strstr(tmpCourse.name, keyPartName)!= NULL && tmpCourse.status == 0){
               fclose(fp);
               return &tmpCourse;
            }
       }
       return NULL;
    }else{ //BUSCA POR NOME E CODIGO
        while (!feof(fp)) {
            fread(&tmpCourse, sizeof(structCourse), 1, fp);
            if(!strcmp(tmpCourse.code, keyCode) && !strcmp(tmpCourse.name, keyName) && tmpCourse.status == 0){
                    fclose(fp);
            return &tmpCourse;
            }
        }
        return NULL;
    }

    return NULL;
}

//PRINTA NO CONSOLE OS DADOS DO CURSO PASSADO COMO PARAMETRO
void printCourseFile(structCourse *course){
    if(course == NULL){
        printf("\nNenhum curso encontrado com os dados informados.\n");
        system("pause");
    }else{
        structCourse tmpCourse = *course;

        printf("\nCODIGO: %s\n", tmpCourse.code);
        printf("NOME: %s\n", tmpCourse.name);
        printf("DESCRICAO: %s\n", tmpCourse.description);
        printf("SEMESTRES: %d\n", tmpCourse.semesters);
        system("pause");
    }
}
//LISTA OS CURSOS CADASTRADOS NO SISTEMA
void listCourseFile(char keyName[]){
    structCourse tmpCourse;

    fp = fopen("myCourse", "r+b");
    if(!fp){
        printf("O arquivo nao pode ser aberto. Encerrando o programa...\n");
        system("pause");
        exit(0);
    }

    rewind(fp);

    printf("\n\nCURSOS CADASTRADOS\n\n");
    printf("%-6s %-20s\n", "******", "*******************");
    printf("%-6s %-20s\n", "CODIGO", "NOME");
    printf("%-6s %-20s\n", "******", "*******************");

    if(strlen(keyName) == 0){ //LISTAGEM COMPLETA
        while (!feof(fp)) {
        if(fread(&tmpCourse, sizeof(structCourse), 1, fp))
            if(tmpCourse.status == 0) //LISTA TODOS
            printf("%-6s %-20s\n", tmpCourse.code, tmpCourse.name);
        }
    }else{  //LISTAGEM POR PARTE DO NOME
        while (!feof(fp)) {
        if(fread(&tmpCourse, sizeof(structCourse), 1, fp))
            if(strstr(tmpCourse.name, keyName) && tmpCourse.status == 0) //LISTA OS QUE POSSUEM PARTE DA KEYNAME INFORMADA
                printf("%-6s %-20s\n", tmpCourse.code, tmpCourse.name);
        }
    }
    system("pause");
    fclose(fp);
}
//USAR NAS ENTRADAS DE DADOS - PASSA OS CARACTERES PARAR MAIÚSCULO
char* strToUpper(char keyName[]){
    int i;
    for (i = 0; keyName[i]; i++)
        keyName[i] = toupper(keyName[i]);

    return keyName;
}
/**------------------------ATUALIZAÇÃO-----------------------------**/
void updCourse(){
    structCourse *course;
    char option;
    char keyCode[6];
    char keyName[20];

    printf("\nSELECIONE UMA OPCAO DE ATUALIZACAO:\n");
    printf("[1] Atualizacao por codigo\n");
    printf("[2] Atualizacao por codigo com listagem\n");
    printf("[3] Atualizacao por nome\n");
    printf("[X] Cancelar\n");

    fflush(stdin);
    option = getchar();

    course= (structCourse*) malloc(sizeof(structCourse));

    switch(option){
        case '1':
            updForCode();
            break;
        case '2':
            updForCodeWithList();
            break;
        case '3':
            updForName();
            break;
        case 'x':
            break;
        case 'X':
            break;
        default:
            break;
    }
}


/**
* Função que recebe a posição do registro no arquivo e realiza a atualização
**/
updCourseFile(int pos){
       structCourse *course;
       course= (structCourse*) malloc(sizeof(structCourse));
        fp= fopen("myCourse","rb+");
           if(fp){
                printf("Informe o novo codigo:");
                fflush(stdin);
                gets(course->code);
                strcpy(course->code,strToUpper(course->code));

                printf("Informe o novo nome:");
                fflush(stdin);
                gets(course->name);
                strcpy(course->name,strToUpper(course->name));

                printf("Informe a nova descricao:");
                fflush(stdin);
                strcpy(course->description,strToUpper(course->description));


                printf("Informe a nova qtd. de semestres:");
                fflush(stdin);
                scanf("%d",&course->semesters);
                course->status=0;

                fseek(fp,sizeof(structCourse)*pos,SEEK_SET);
                if(fwrite(course,sizeof(structCourse),1,fp)==1)
                   printf("Curso Atualizado com sucesso!\n");
                else
                   printf("Erro ao atualizar curso!\n");
                fclose(fp);
           }
           system("pause");
         }

/**
* Função que atualiza curso através da busca por código
**/
updForCode(){
   FILE* fp = fopen("myCourse","rb");
   int pos=0,flagFound=NOTFOUND;
   char keyCode[6];

   if(fp){
       structCourse *course;
       course= (structCourse*) malloc(sizeof(structCourse));

         printf("Informe o codigo:");
         fflush(stdin);
         gets(keyCode);

        /*Busca do registro*/
        while(!feof(fp)){
            fread(course,sizeof(structCourse),1,fp);
            if((strcmp(course->code,strToUpper(keyCode))==0 )&& (course->status == 0)){
                printCourseFile(course);
                updCourseFile(pos);
                flagFound=FOUND;
            }
            pos++;
         }
         fclose(fp);
         if(flagFound==NOTFOUND){
            printf("Curso nao encontrado.\n");
            system("PAUSE");
         }
    }
}

/**
* Função que mostra uma lista e depois atualiza curso através da busca por código
**/
updForCodeWithList(){
   FILE* fp = fopen("myCourse","rb");
   int pos=0,flagFound=NOTFOUND;
   char keyCode[6];

   if(fp){
       structCourse *course;
       course= (structCourse*) malloc(sizeof(structCourse));
        listCourseFile("");
         printf("Informe o codigo:");
         fflush(stdin);
         gets(keyCode);

        while(!feof(fp)){
            fread(course,sizeof(structCourse),1,fp);
            if((strcmp(course->code,strToUpper(keyCode))==0) &&(course->status == 0)){
                updCourseFile(pos);
                flagFound=FOUND;
            }
            pos++;
         }
         fclose(fp);
         if(flagFound==NOTFOUND){
            printf("Curso nao encontrado.\n");
            system("PAUSE");
         }
    }
}

/**
* Função que atualiza curso através da busca pelo nome ou por parte dele
**/
updForName(){
   FILE* fp = fopen("myCourse","rb");
   int pos=0,flagFound=NOTFOUND;
   char keyName[20];

   if(fp){
       structCourse *course;
       course= (structCourse*) malloc(sizeof(structCourse));
         printf("Informe o nome ou parte dele:");
         fflush(stdin);
         gets(keyName);

        while(!feof(fp)){
            fread(course,sizeof(structCourse),1,fp);
            if((strstr(course->name,strToUpper(keyName))!=NULL) && (course->status == 0)){
                printCourseFile(course);
                updCourseFile(pos);
                flagFound=FOUND;
            }
            pos++;
         }
         fclose(fp);
         if(flagFound==NOTFOUND){
            printf("Curso nao encontrado.\n");
            system("PAUSE");
         }
    }
}

/**------------------------DELEÇÃO-----------------------------**/



/**
* Função que recebe a posição do registro no arquivo e realiza a remoção
**/
delCourseFile(int pos){
       structCourse *course;
       course= (structCourse*) malloc(sizeof(structCourse));
        fp= fopen("myCourse","rb+");
           if(fp){
                course->status=-1;

                fseek(fp,sizeof(structCourse)*pos,SEEK_SET);
                if(fwrite(course,sizeof(structCourse),1,fp)==1)
                   printf("Curso Removido com sucesso!\n");
                else
                   printf("Erro ao remover curso!\n");
                fclose(fp);
           }
           system("pause");
         }

/**
* Função que remove curso através da busca por código
**/
delForCode(){
   FILE* fp = fopen("myCourse","rb");
   int pos=0,flagFound=NOTFOUND;
   char keyCode[6];

   if(fp){
       structCourse *course;
       course= (structCourse*) malloc(sizeof(structCourse));

         printf("Informe o codigo:");
         fflush(stdin);
         gets(keyCode);

        /*Busca do registro*/
        while(!feof(fp)){
            fread(course,sizeof(structCourse),1,fp);
            if(strcmp(course->code,strToUpper(keyCode))==0){
                printCourseFile(course);
                delCourseFile(pos);
                flagFound=FOUND;
            }
            pos++;
         }
         fclose(fp);
         if(flagFound==NOTFOUND){
            printf("Curso nao encontrado.\n");
            system("PAUSE");
         }
    }
}

/**
* Função que mostra uma lista e depois remove curso através da busca por código
**/
delForCodeWithList(){
   FILE* fp = fopen("myCourse","rb");
   int pos=0,flagFound=NOTFOUND;
   char keyCode[6];

   if(fp){
       structCourse *course;
       course= (structCourse*) malloc(sizeof(structCourse));
        listCourseFile("");
         printf("Informe o codigo:");
         fflush(stdin);
         gets(keyCode);

        while(!feof(fp)){
            fread(course,sizeof(structCourse),1,fp);
            if(strcmp(course->code,strToUpper(keyCode))==0){
                delCourseFile(pos);
                flagFound=FOUND;
            }
            pos++;
         }
         fclose(fp);
         if(flagFound==NOTFOUND){
            printf("Curso nao encontrado.\n");
            system("PAUSE");
         }
    }
}

/**
* Função que remove curso através da busca pelo nome ou por parte dele
**/
delForName(){
   FILE* fp = fopen("myCourse","rb");
   int pos=0,flagFound=NOTFOUND;
   char keyName[20];

   if(fp){
       structCourse *course;
       course= (structCourse*) malloc(sizeof(structCourse));
         printf("Informe o nome ou parte dele:");
         fflush(stdin);
         gets(keyName);

        while(!feof(fp)){
            fread(course,sizeof(structCourse),1,fp);
            if(strstr(course->name,strToUpper(keyName))!=NULL){
                printCourseFile(course);
                delCourseFile(pos);
                flagFound=FOUND;
            }
            pos++;
         }
         fclose(fp);
         if(flagFound==NOTFOUND){
            printf("Curso nao encontrado.\n");
            system("PAUSE");
         }
    }
}


